home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d16 / winutil1.arc / ELEMEN.ARC / ELEMENT.C next >
C/C++ Source or Header  |  1990-11-07  |  11KB  |  374 lines

  1. //
  2. // Periodic table of the elements, for Microsoft Windows 3.0.
  3. // Written by Gregory A. Jones, uunet!microsoft!gregj.
  4. // This program may be freely distributed.
  5. // Chemical data culled from reference works, including the
  6. //    CRC Handbook of Chemistry and Physics.
  7. //
  8.  
  9. #include <windows.h>
  10. #include "element.h"
  11.  
  12. //
  13. // Prototypes for exported functions.
  14. //
  15.  
  16. long FAR PASCAL WndProc (HWND, unsigned, WORD, LONG);
  17. BOOL FAR PASCAL DetailDlgProc (HWND, unsigned, WORD, LONG);
  18.  
  19. //
  20. // A few global variables.
  21. //
  22.  
  23. char szAppName [] = "PTable";
  24. HANDLE ghInstance;
  25. int iElement;
  26.  
  27. //
  28. // Data stored for each element.  Includes name, symbol, atomic weight,
  29. // and location in table (where period one is row 0, family 1a is column 0).
  30. // Atomic number is implicit, since the table is ordered by it.
  31. //
  32.  
  33. typedef struct tagELEMENT {
  34.     char *pszName;    // Name of the element, i.e. "Hydrogen"
  35.     char *pszSymbol;    // Symbol, i.e. "He"
  36.     char *pszWeight;    // Atomic weight, i.e. "(230)"
  37.     WORD wColumn;    // Column number to draw in
  38.     WORD wRow;        // Row number to draw in
  39. } ELEMENT;
  40.  
  41. typedef ELEMENT *PELEMENT;
  42.  
  43. //
  44. // Width and height of the table, and number of elements defined.
  45. //
  46.  
  47. #define NUM_COLUMNS    18
  48. #define NUM_ROWS    10
  49. #define MAX_ELEMENTS    106
  50.  
  51. //
  52. // Titles for the families, by column.  Null strings are because "8"
  53. // really covers three columns.
  54. //
  55.  
  56. char *pszTitles [NUM_COLUMNS] = {
  57. "1a", "2a", "3b", "4b", "5b", "6b", "7b", "", "8", "", "1b", "2b",
  58. "3a", "4a", "5a", "6a", "7a", "0"
  59. };
  60.  
  61. //
  62. // The elements themselves.  Add new ones on the end if you discover them.
  63. //
  64.  
  65. ELEMENT elTable [MAX_ELEMENTS] = {
  66. "Hydrogen", "H", "1.0079", 0, 0,
  67. "Helium", "He", "4.00260", 17, 0,
  68. "Lithium", "Li", "6.94", 0, 1,
  69. "Beryllium", "Be", "9.01218", 1, 1,
  70. "Boron", "B", "10.81", 12, 1,
  71. "Carbon", "C", "12.011", 13, 1,
  72. "Nitrogen", "N", "14.0067", 14, 1,
  73. "Oxygen", "O", "15.9994", 15, 1,
  74. "Fluorine", "F", "18.998403", 16, 1,
  75. "Neon", "Ne", "20.17", 17, 1,
  76. "Sodium", "Na", "22.98977", 0, 2,
  77. "Magnesium", "Mg", "24.305", 1, 2,
  78. "Aluminum", "Al", "26.98154", 12, 2,
  79. "Silicon", "Si", "28.0855", 13, 2,
  80. "Phosphorous", "P", "30.97376", 14, 2,
  81. "Sulfur", "S", "32.06", 15, 2,
  82. "Chlorine", "Cl", "35.453", 16, 2,
  83. "Argon", "Ar", "39.948", 17, 2,
  84. "Potassium", "K", "39.0983", 0, 3,
  85. "Calcium", "Ca", "40.08", 1, 3,
  86. "Scandium", "Sc", "44.9559", 2, 3,
  87. "Titanium", "Ti", "47.90", 3, 3,
  88. "Vanadium", "V", "50.9415", 4, 3,
  89. "Chromium", "Cr", "51.996", 5, 3,
  90. "Manganese", "Mn", "54.9380", 6, 3,
  91. "Iron", "Fe", "55.847", 7, 3,
  92. "Cobalt", "Co", "58.9332", 8, 3,
  93. "Nickel", "Ni", "58.71", 9, 3,
  94. "Copper", "Cu", "63.546", 10, 3,
  95. "Zinc", "Zn", "65.38", 11, 3,
  96. "Gallium", "Ga", "69.735", 12, 3,
  97. "Germanium", "Ge", "72.59", 13, 3,
  98. "Arsenic", "As", "74.9216", 14, 3,
  99. "Selenium", "Se", "78.96", 15, 3,
  100. "Bromium", "Br", "79.904", 16, 3,
  101. "Krypton", "Kr", "83.80", 17, 3,
  102. "Rubidium", "Rb", "85.467", 0, 4,
  103. "Strontium", "Sr", "87.62", 1, 4,
  104. "Yttrium", "Y", "88.9059", 2, 4,
  105. "Zirconium", "Zr", "91.22", 3, 4,
  106. "Niobium", "Nb", "92.9064", 4, 4,
  107. "Molybdenum", "Mo", "95.94", 5, 4,
  108. "Technetium", "Tc", "98.9062", 6, 4,
  109. "Ruthenium", "Ru", "101.07", 7, 4,
  110. "Rhodium", "Rh", "102.9055", 8, 4,
  111. "Palladium", "Pd", "106.4", 9, 4,
  112. "Silver", "Ag", "107.868", 10, 4,
  113. "Cadmium", "Cd", "112.41", 11, 4,
  114. "Indium", "In", "114.82", 12, 4,
  115. "Tin", "Sn", "118.69", 13, 4,
  116. "Antimony", "Sb", "121.75", 14, 4,
  117. "Tellurium", "Te", "127.60", 15, 4,
  118. "Iodine", "I", "126.9045", 16, 4,
  119. "Xenon", "Xe", "131.30", 17, 4,
  120. "Cesium", "Cs", "132.9054", 0, 5,
  121. "Barium", "Ba", "137.33", 1, 5,
  122. "Lanthanum", "La", "138.9055", 2, 5,
  123. "Cerium", "Ce", "140.12", 2, 8,
  124. "Praeseodymium", "Pr", "140.9077", 3, 8,
  125. "Neodymium", "Nd", "144.24", 4, 8,
  126. "Promethium", "Pm", "(145)", 5, 8,
  127. "Samarium", "Sm", "150.4", 6, 8,
  128. "Europium", "Eu", "151.96", 7, 8,
  129. "Gadolinium", "Gd", "157.25", 8, 8,
  130. "Terbium", "Tb", "158.9254", 9, 8,
  131. "Dysprosium", "Dy", "162.50", 10, 8,
  132. "Holmium", "Ho", "164.9304", 11, 8,
  133. "Erbium", "Er", "167.26", 12, 8,
  134. "Thulium", "Tm", "168.9342", 13, 8,
  135. "Ytterbium", "Yb", "173.04", 14, 8,
  136. "Lutetium", "Lu", "174.96", 15, 8,
  137. "Hafnium", "Hf", "178.49", 3, 5,
  138. "Tantalum", "Ta", "180.947", 4, 5,
  139. "Tungsten", "W", "183.85", 5, 5,
  140. "Rhenium", "Re", "186.207", 6, 5,
  141. "Osmium", "Os", "190.2", 7, 5,
  142. "Iridium", "Ir", "192.22", 8, 5,
  143. "Platinum", "Pt", "195.09", 9, 5,
  144. "Gold", "Au", "196.9665", 10, 5,
  145. "Mercury", "Hg", "200.59", 11, 5,
  146. "Thallium", "Tl", "204.37", 12, 5,
  147. "Lead", "Pb", "207.2", 13, 5,
  148. "Bismuth", "Bi", "208.9804", 14, 5,
  149. "Polonium", "Po", "(209)", 15, 5,
  150. "Astatine", "At", "(210)", 16, 5,
  151. "Radon", "Rn", "(222)", 17, 5,
  152. "Francium", "Fr", "(223)", 0, 6,
  153. "Radium", "Ra", "226.0254", 1, 6,
  154. "Actinium", "Ac", "(227)", 2, 6,
  155. "Thorium", "Th", "232.0381", 2, 9,
  156. "Protactinium", "Pa", "231.0359", 3, 9,
  157. "Uranium", "U", "238.029", 4, 9,
  158. "Neptunium", "Np", "237.0482", 5, 9,
  159. "Plutonium", "Pu", "(244)", 6, 9,
  160. "Americium", "Am", "(243)", 7, 9,
  161. "Curium", "Cm", "(247)", 8, 9,
  162. "Berkelium", "Bk", "(247)", 9, 9,
  163. "Calfornium", "Cf", "(251)", 10, 9,
  164. "Einsteinium", "Es", "(254)", 11, 9,
  165. "Fermium", "Fm", "(257)", 12, 9,
  166. "Mendelevium", "Md", "(258)", 13, 9,
  167. "Nobelium", "No", "(259)", 14, 9,
  168. "Lawrencium", "Lr", "(260)", 15, 9,
  169. "Rutherfordium", "Rf", "(260)", 3, 6,
  170. "Hahnium", "Ha", "(260)", 4, 6,
  171. "Element 106", "106", "(263)", 5, 6
  172. };
  173.  
  174. //
  175. // Main entrypoint for this application.
  176. //
  177.  
  178. int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
  179.             LPSTR lpszCmdLine, int nCmdShow)
  180. {
  181.     HWND hWnd;
  182.     MSG msg;
  183.     WNDCLASS wndclass;
  184.  
  185.     ghInstance = hInstance;
  186.  
  187.     //
  188.     // Register the window class for this application.
  189.     //
  190.  
  191.     if (!hPrevInstance) {
  192.     wndclass.style = CS_VREDRAW | CS_HREDRAW;
  193.     wndclass.lpfnWndProc = WndProc;
  194.     wndclass.cbClsExtra = 0;
  195.     wndclass.cbWndExtra = 0;
  196.     wndclass.hInstance = hInstance;
  197.     wndclass.hIcon = LoadIcon (hInstance, "mainicon");
  198.     wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
  199.     wndclass.hbrBackground = GetStockObject (WHITE_BRUSH);
  200.     wndclass.lpszMenuName = NULL;
  201.     wndclass.lpszClassName = szAppName;
  202.  
  203.     if (!RegisterClass (&wndclass))
  204.         return FALSE;
  205.     }
  206.  
  207.     //
  208.     // Create and display the main window.
  209.     //
  210.  
  211.     hWnd = CreateWindow (szAppName, "Periodic Table", WS_OVERLAPPED |
  212.             WS_CAPTION | WS_THICKFRAME | WS_SYSMENU |
  213.             WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_MAXIMIZE,
  214.             CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL,
  215.             hInstance, NULL);
  216.  
  217.     ShowWindow (hWnd, SW_SHOWMAXIMIZED);
  218.  
  219.     UpdateWindow (hWnd);
  220.  
  221.     //
  222.     // Process messages.
  223.     //
  224.  
  225.     while (GetMessage (&msg, NULL, 0, 0)) {
  226.     TranslateMessage (&msg);
  227.     DispatchMessage (&msg);
  228.     }
  229.  
  230.     return msg.wParam;
  231. }
  232.  
  233. long FAR PASCAL WndProc (HWND hWnd, unsigned iMessage, WORD wParam, LONG lParam)
  234. {
  235.     static WORD cxClient, cyClient, cxBox, cyBox;
  236.     int i, cyChar, xBox, yBox;
  237.     PAINTSTRUCT ps;
  238.     HDC hDC;
  239.     PELEMENT pel;
  240.     char buf [10];
  241.     RECT rect;
  242.     FARPROC lpfnDialogProc;
  243.  
  244.     switch (iMessage) {
  245.     case WM_SIZE:
  246.         //
  247.         // When the window changes size, update static variables
  248.         // containing the window size and size of each box.
  249.         //
  250.         cxClient = LOWORD (lParam);
  251.         cyClient = HIWORD (lParam);
  252.         cxBox = (cxClient - 40) / NUM_COLUMNS;
  253.         cyBox = (cyClient - 60) / NUM_ROWS;
  254.         break;
  255.  
  256.     case WM_LBUTTONDOWN:
  257.     case WM_RBUTTONDOWN:
  258.     case WM_MBUTTONDOWN:
  259.         //
  260.         // Mouse click.  Calculate which box the mouse pointer is in,
  261.         // then look for which element is in that box.
  262.         //
  263.         xBox = (LOWORD (lParam) - 20) / cxBox;
  264.         yBox = (HIWORD (lParam) - 40) / cyBox;
  265.  
  266.         for (i=0; i<MAX_ELEMENTS; i++)
  267.         if (elTable [i].wColumn == xBox &&
  268.             elTable [i].wRow == yBox)
  269.             break;
  270.  
  271.         if (i == MAX_ELEMENTS)
  272.         return 0L;
  273.  
  274.         //
  275.         // Found the element.  Store the desired table index in a global
  276.         // variable, then load the details dialog.
  277.         //
  278.         iElement = i;
  279.         lpfnDialogProc = MakeProcInstance (DetailDlgProc, ghInstance);
  280.         DialogBox (ghInstance, "DETAILS", hWnd, lpfnDialogProc);
  281.         FreeProcInstance (lpfnDialogProc);
  282.         return 0L;
  283.  
  284.     case WM_PAINT:
  285.         //
  286.         // Need to redraw the window.
  287.         //
  288.         hDC = BeginPaint (hWnd, &ps);
  289.         cyChar = HIWORD (GetTextExtent (hDC, "M", 1));
  290.  
  291.         rect.top = cyChar;
  292.         rect.bottom = cyChar * 2 + 2;
  293.  
  294.         //
  295.         // Draw the column titles.
  296.         //
  297.         for (i=0; i<NUM_COLUMNS; i++) {
  298.         rect.left = i * cxBox + 20;
  299.         rect.right = rect.left + cxBox;
  300.         DrawText (hDC, pszTitles [i], -1, &rect, DT_CENTER | DT_VCENTER |
  301.             DT_NOPREFIX | DT_SINGLELINE);
  302.         }
  303.  
  304.         //
  305.         // Now draw each element.  Each one consists of a rectangle to
  306.         // contain the information, the atomic number in the upper left
  307.         // corner, and the atomic symbol centered.
  308.         //
  309.         for (i=0; i<MAX_ELEMENTS; i++) {
  310.         pel = &elTable [i];
  311.         rect.left = pel->wColumn * cxBox + 20;
  312.         rect.right = rect.left + cxBox;
  313.         rect.top = pel->wRow * cyBox + 40;
  314.         rect.bottom = rect.top + cyBox;
  315.         Rectangle (hDC, rect.left, rect.top, rect.right, rect.bottom);
  316.  
  317.         wsprintf (buf, "%i", i+1);
  318.         TextOut (hDC, rect.left+1, rect.top+1, buf, lstrlen (buf));
  319.  
  320.         rect.top += cyChar + 1;
  321.  
  322.         DrawText (hDC, pel->pszSymbol, -1, &rect, DT_CENTER | DT_VCENTER |
  323.             DT_NOPREFIX | DT_SINGLELINE);
  324.         }
  325.  
  326.         EndPaint (hWnd, &ps);
  327.         return 0L;
  328.  
  329.     case WM_DESTROY:
  330.         //
  331.         // Main window closed.  Quit the program.
  332.         //
  333.         PostQuitMessage (0);
  334.         return 0L;
  335.     }
  336.  
  337.     return DefWindowProc (hWnd, iMessage, wParam, lParam);
  338. }
  339.  
  340. //
  341. // Window procedure for details dialog box.
  342. //
  343. BOOL FAR PASCAL DetailDlgProc (HWND hWnd, unsigned msg, WORD wParam, LONG lParam)
  344. {
  345.     char buf [10];
  346.  
  347.     switch (msg) {
  348.     case WM_INITDIALOG:
  349.         //
  350.         // Dialog just got loaded.  Set up the static text fields
  351.         // with the information about the element.
  352.         //
  353.         SetDlgItemText (hWnd, ID_NAME, elTable [iElement].pszName);
  354.         SetDlgItemText (hWnd, ID_SYMBOL, elTable [iElement].pszSymbol);
  355.         wsprintf (buf, "%i", iElement+1);
  356.         SetDlgItemText (hWnd, ID_NUMBER, buf);
  357.         SetDlgItemText (hWnd, ID_WEIGHT, elTable [iElement].pszWeight);
  358.         return TRUE;
  359.  
  360.     case WM_COMMAND:
  361.         //
  362.         // Command of some sort.  If it was the OK button, or the close
  363.         // box, dismiss the dialog.
  364.         //
  365.         if (wParam == IDOK || wParam == IDCANCEL) {
  366.         EndDialog (hWnd, 0);
  367.         return TRUE;
  368.         }
  369.         else
  370.         return FALSE;
  371.     }
  372.     return FALSE;
  373. }
  374.